#include <Arduino.h>
#include <NimBLEDevice.h>

#define LED_PIN 2

// 定义 心率和电量 服务ID
#define HEART_RATE_SERVICE_UUID "180D"
#define BATTERY_SERVICE_UUID "180F"

// 定义 心率和电量 特征值ID
#define HEART_RATE_MEASUREMENT_UUID "2A37"
#define BATTERY_LEVEL_UUID "2A19"

NimBLECharacteristic *pHeartRateCharacteristic = nullptr;
NimBLECharacteristic *pBatteryCharacteristic = nullptr;
bool deviceConnected = false;

// 心率当前值
volatile uint8_t hr = 59;
volatile uint8_t bat = 100;

std::string name_prefix = "Polar";
std::string local_mac;

// 软件定时器
hw_timer_t *hw_timer_0 = nullptr;

void led_off() {
    digitalWrite(LED_PIN, LOW);
}

void notify() {
    if (deviceConnected) {
        if (hr == 200) {
            hr = 59;
            bat--;
            if (bat == 1) {
                bat = 100;
            }
            const uint8_t batData[1] = {bat};
            pBatteryCharacteristic->setValue(batData, 1);
            const bool battery_notify = pBatteryCharacteristic->notify();
            if (battery_notify) {
                Serial.print("current battery level ");
                Serial.println(bat);
            }
        }
        hr++;
        const uint8_t hrData[2] = {0x00, hr};
        pHeartRateCharacteristic->setValue(hrData, 2);
        const bool heart_rate_notify = pHeartRateCharacteristic->notify();
        if (heart_rate_notify) {
            Serial.print("current heart rate ");
            Serial.println(hr);
            digitalWrite(LED_PIN, !digitalRead(LED_PIN));
            delay(50);
            digitalWrite(LED_PIN, !digitalRead(LED_PIN));
            delay(50);
        }
    } else {
        Serial.print(local_mac.c_str());
        Serial.println(" waiting to be connected");
    }
}


class ServerCallbacks final : public NimBLEServerCallbacks {
    void onConnect(NimBLEServer *pServer, NimBLEConnInfo &connInfo) override {
        deviceConnected = true;

        // 关闭定时器
        timerAlarmDisable(hw_timer_0);

        Serial.print(local_mac.c_str());
        Serial.println(" has been connected");

        led_off();
    };

    void onDisconnect(NimBLEServer *pServer, NimBLEConnInfo &connInfo, int reason) override {
        deviceConnected = false;

        // 启动定时器
        timerAlarmEnable(hw_timer_0);

        NimBLEAdvertising *pAdvertising = NimBLEDevice::getAdvertising();
        pAdvertising->start();
    }
} serverCallbacks;

// 定时器中断服务函数
void switch_led_timer_interrupt() {
    digitalWrite(LED_PIN, !digitalRead(LED_PIN));
}

void setup() {
    Serial.begin(9600);
    pinMode(LED_PIN, OUTPUT);

    // 初始化硬件定时器0（TIMER_0，分频系数80，向上计数）
    hw_timer_0 = timerBegin(0, 80, true); // 80分频 → 1MHz时钟（ESP32主频80MHz）
    timerAttachInterrupt(hw_timer_0, &switch_led_timer_interrupt, true); // 绑定中断函数
    timerAlarmWrite(hw_timer_0, 100000, true); // 100ms触发一次

    NimBLEDevice::init("心率模拟器");

    NimBLEServer *pServer = NimBLEDevice::createServer();
    local_mac = NimBLEDevice::getAddress().toString();

    auto end = std::remove(local_mac.begin(), local_mac.end(), ':');
    local_mac.erase(end, local_mac.end());
    std::transform(local_mac.begin(), local_mac.end(), local_mac.begin(), toupper);

    pServer->setCallbacks(&serverCallbacks);

    // 创建心率特征 (通知 + 读)
    BLEService *pHeartService = pServer->createService(NimBLEUUID(HEART_RATE_SERVICE_UUID));
    pHeartRateCharacteristic = pHeartService->createCharacteristic(NimBLEUUID(HEART_RATE_MEASUREMENT_UUID),
                                                                   NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::NOTIFY);
    pHeartService->start();

    // 创建电池服务 (通知 + 读)
    BLEService *pBatteryService = pServer->createService(BATTERY_SERVICE_UUID);
    pBatteryCharacteristic = pBatteryService->createCharacteristic(BATTERY_LEVEL_UUID,
                                                                   NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::NOTIFY);
    pBatteryService->start();

    NimBLEAdvertising *pAdvertising = NimBLEDevice::getAdvertising();

    pAdvertising->setName(name_prefix + local_mac);
    pAdvertising->addServiceUUID(pHeartService->getUUID());
    pAdvertising->addServiceUUID(pBatteryService->getUUID());
    pAdvertising->start();

    // 启动定时器
    timerAlarmEnable(hw_timer_0);
}

void loop() {
    notify();
    delay(900);
}
